<template>
  <div>
    <!-- 浮动按钮 -->
    <div
      ref="button"
      class="float-button"
      :style="{ top: buttonTop + 'px', left: buttonLeft + 'px' }"
      @mousedown="startDrag('button')"
      @click.stop="toggleDialog"
    >
      🚀 AI助手
    </div>

    <!-- 浮动弹窗 -->
    <div
      v-if="dialogVisible"
      class="float-dialog"
      :style="{
        top: dialogTop + 'px',
        left: dialogLeft + 'px',
        width: dialogWidth + 'px',
        height: dialogHeight + 'px'
      }"
    >
      <div
        class="dialog-header"
        @mousedown.stop="startDrag('dialog')"
      >
        <span class="header-title">AI助手</span>
        <el-button
          class="close-btn"
          type="text"
          @click.stop="dialogVisible = false"
          icon="el-icon-close"
        ></el-button>
      </div>
      <div class="dialog-content">
        <!-- 对话内容 -->
        <div
          v-for="(msg, index) in messages"
          :key="index"
          :class="['message-bubble', msg.role]"
        >
          <div class="message-content markdown-body"
               v-html="renderMarkdown(msg.content)">
          </div>
          <!-- 加载指示器 -->
          <div v-if="msg.isStreaming" class="streaming-indicator">
            <div class="dot-flashing"></div>
          </div>
        </div>
      </div>
      <div class="input-area">
        <el-input
          v-model="inputMsg"
          placeholder="请输入您的问题..."
          :disabled="isWaiting"
          @keyup.enter.native="sendMessage"
        >
          <el-button
            slot="append"
            :icon="isWaiting ? 'el-icon-loading' : 'el-icon-position'"
            :disabled="isWaiting"
            @click="sendMessage"
          ></el-button>
        </el-input>
      </div>

      <!-- 尺寸调整手柄 -->
      <div
        class="resize-handle"
        @mousedown.stop="startResize"
      ></div>
    </div>
  </div>
</template>

<script>
import MarkdownIt from 'markdown-it'
import DOMPurify from 'dompurify'

export default {
  name: 'GlobalDialog',
  data() {
    return {
      dialogVisible: false,
      inputMsg: '',
      messages: [
        {
          role: 'ai',
          content: '您好！我是AI助手，有什么可以帮您的吗？',
          isStreaming: false
        }
      ],
      buttonTop: 20,
      buttonLeft: 20,
      dialogTop: 100,
      dialogLeft: 100,
      dialogWidth: 400,
      dialogHeight: 400,
      isDragging: false,
      currentDragTarget: null,
      isResizing: false,
      startX: 0,
      startY: 0,
      session_id: undefined,
      hasMoved: false,
      isWaiting: false,      // 新增等待状态
      currentStreamIndex: -1 // 当前流式消息索引
    }
  },
  methods: {
    renderMarkdown(content) {
      const md = new MarkdownIt({
        html: true,
        linkify: true,
        typographer: true
      })
      const rawHtml = md.render(content)
      return DOMPurify.sanitize(rawHtml)
    },
    async callDashScope(prompt) {
      try {
        const apiKey = 'sk-27c74a22cc2649599fd132c41d70aa69';
        const appId = 'd2c4653a3b9b42f7a9960ad87380886c';

        const url = `https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`;

        const data = {
          input: {
            prompt: prompt,
          },
          parameters: {
            'incremental_output': 'true'
          },
          debug: {}
        };
        if (this.session_id) {
          data.input.session_id = this.session_id;
        }

        const response = await fetch(url, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json',
            'X-DashScope-SSE': 'enable'
          },
          body: JSON.stringify(data)
        });

        if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        // 标记当前消息索引
        this.currentStreamIndex = this.messages.length - 1;

        while (true) {
          const { done, value } = await reader.read();
          if (done) {
            this.messages[this.currentStreamIndex].isStreaming = false;
            console.log(this.messages[this.messages.length - 1].content)
            break;
          }

          const chunk = decoder.decode(value, { stream: true });
          buffer += chunk;

          const dataLine = chunk.split('\n').find(line => line.startsWith('data:')).substring(5);
          const jsonObj = JSON.parse(dataLine);

          const currentSessionId = jsonObj.output.session_id;
          const text = jsonObj.output.text;

          if (text) {
            this.messages[this.currentStreamIndex].content += text;
          }

          if (!this.session_id && currentSessionId) {
            this.session_id = currentSessionId;
            data.input.session_id = this.session_id;
          }
        }
      } catch (error) {
        console.error('API请求失败:', error);
        this.messages[this.currentStreamIndex].content += "\n【服务暂时不可用，请稍后再试】";
      } finally {
        this.isWaiting = false;
        this.messages[this.currentStreamIndex].isStreaming = false;
      }
    },
    toggleDialog() {
      if (this.hasMoved) {
        this.hasMoved = false;
        return;
      }
      this.dialogVisible = !this.dialogVisible
    },
    startDrag(target) {
      this.currentDragTarget = target
      this.isDragging = true
      this.hasMoved = false
      document.addEventListener('mousemove', this.onDrag)
      document.addEventListener('mouseup', this.stopDrag)
    },
    onDrag(e) {
      if (!this.isDragging) return
      this.hasMoved = true

      const target = this.currentDragTarget
      const viewportWidth = window.innerWidth
      const viewportHeight = window.innerHeight
      const offset = target === 'button' ? {x: 50, y: 20} : {x: 200, y: 50}

      let newLeft = e.clientX - offset.x
      let newTop = e.clientY - offset.y

      if (target === 'button') {
        const buttonWidth = this.$refs.button.offsetWidth
        const buttonHeight = this.$refs.button.offsetHeight
        newLeft = Math.max(0, Math.min(newLeft, viewportWidth - buttonWidth))
        newTop = Math.max(0, Math.min(newTop, viewportHeight - buttonHeight))
      } else {
        newLeft = Math.max(0, Math.min(newLeft, viewportWidth - this.dialogWidth))
        newTop = Math.max(0, Math.min(newTop, viewportHeight - this.dialogHeight))
      }

      this[`${target}Left`] = newLeft
      this[`${target}Top`] = newTop
    },
    stopDrag() {
      this.isDragging = false
      document.removeEventListener('mousemove', this.onDrag)
      document.removeEventListener('mouseup', this.stopDrag)
    },
    startResize(e) {
      this.isResizing = true
      this.startX = e.clientX
      this.startY = e.clientY
      document.addEventListener('mousemove', this.handleResize)
      document.addEventListener('mouseup', this.stopResize)
    },
    handleResize(e) {
      if (!this.isResizing) return

      const deltaX = e.clientX - this.startX
      const deltaY = e.clientY - this.startY

      this.dialogWidth = Math.max(300, this.dialogWidth + deltaX)
      this.dialogHeight = Math.max(200, this.dialogHeight + deltaY)

      const viewportWidth = window.innerWidth
      const viewportHeight = window.innerHeight
      this.dialogLeft = Math.min(Math.max(this.dialogLeft, 0), viewportWidth - this.dialogWidth)
      this.dialogTop = Math.min(Math.max(this.dialogTop, 0), viewportHeight - this.dialogHeight)

      this.startX = e.clientX
      this.startY = e.clientY
    },
    stopResize() {
      this.isResizing = false
      document.removeEventListener('mousemove', this.handleResize)
      document.removeEventListener('mouseup', this.stopResize)
    },
    sendMessage() {
      if (!this.inputMsg.trim() || this.isWaiting) return

      this.isWaiting = true
      this.messages.push({
        role: 'user',
        content: this.inputMsg
      })

      this.messages.push({
        role: 'ai',
        content: '',
        isStreaming: true
      })

      this.scrollToBottom()
      this.callDashScope(this.inputMsg.toString())
      this.inputMsg = ''
    },
    scrollToBottom() {
      this.$nextTick(() => {
        const container = this.$el.querySelector('.dialog-content')
        container.scrollTop = container.scrollHeight
      })
    }
  }
}
</script>

<style scoped>
/* 新增加载动画 */
.dot-flashing {
  position: relative;
  width: 40px;
  height: 20px;
  margin-left: 10px;
}

.dot-flashing::before,
.dot-flashing::after {
  content: "";
  position: absolute;
  top: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #409EFF;
  animation: dot-flashing 1s infinite linear alternate;
}

.dot-flashing::before {
  left: 0;
  animation-delay: 0s;
}

.dot-flashing::after {
  left: 15px;
  animation-delay: 0.5s;
}

@keyframes dot-flashing {
  0% {
    opacity: 0.2;
    transform: translateY(0);
  }
  50% {
    opacity: 1;
    transform: translateY(-4px);
  }
  100% {
    opacity: 0.2;
    transform: translateY(0);
  }
}

.streaming-indicator {
  display: flex;
  align-items: center;
  height: 20px;
  margin-top: 8px;
}

/* 调整消息气泡布局 */
.message-bubble {
  display: flex;
  flex-direction: column;
  margin-bottom: 15px;
}

.message-content {
  max-width: 80%;
  text-align: left;
  margin-left: 10px;
  padding: 10px 15px;
  border-radius: 15px;
  word-break: break-word;
  position: relative;
}

.user .message-content {
  text-align: right;
  margin-left: auto;
  margin-right: 10px;
}

/* 按钮加载动画 */
.el-icon-loading {
  animation: rotating 2s linear infinite;
}

@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* 原有样式保留 */
.markdown-body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  line-height: 1.6;
}

/* 其他原有样式保持不变 */
.resize-handle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 15px;
  height: 15px;
  cursor: nwse-resize;
  background: linear-gradient(135deg,
  transparent 50%,
  #409EFF 50%,
  #409EFF 60%,
  transparent 60%);
}

.float-button {
  position: fixed;
  cursor: move;
  background: #409EFF;
  color: white;
  padding: 10px 20px;
  border-radius: 25px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  user-select: none;
  z-index: 9999;
}

.float-dialog {
  position: fixed;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  min-width: 300px;
  min-height: 200px;
}

.dialog-header {
  padding: 10px 15px;
  background: #409EFF;
  color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: move;
}

.header-title {
  font-weight: 500;
}

.close-btn {
  padding: 0;
  font-size: 18px;
  color: white;
}

.dialog-content {
  flex: 1;
  padding: 15px;
  overflow-y: auto;
  height: calc(100% - 110px);
}

.ai .message-content {
  background: #f5f5f5;
  color: #333;
}

.input-area {
  padding: 15px;
  border-top: 1px solid #eee;
}
</style>
